#include "PlyFileParser.h"
#include <fstream>
#include <string>

using namespace std;

PlyFileParser::PlyFileParser(){
	filename = "";
}

PlyFileParser::PlyFileParser(string _filename): filename(_filename){
}

vector<vector<Point3> > PlyFileParser::parseFile(){
	if(filename.empty()){
		return parseFile(filename);
	}
	else{
		return vector<vector<Point3> >(0);
	}
}

vector<vector<Point3> > PlyFileParser::parseFile(string file){
	ifstream plyFile;
	plyFile.open(file);

	if(!plyFile.is_open() || plyFile.bad()){
		cout << "Error: file \"" + file + "\" could not be opened";
		exit(-1);
	}

	int numVerticies = 0;
	int numFaces = 0;
	string currentWord = "";
	bool counting_params = false;
	int param_count = 0;

	//Read in the configuration & comments
	while(strcmp(currentWord.c_str(), "end_header") != 0){
		plyFile >> currentWord;
		
		if(strcmp(currentWord.c_str(), "element") == 0){
			string secondWord;
			string thirdWord;
			plyFile >> secondWord;
			plyFile >> thirdWord;
			if(strcmp(secondWord.c_str(), "vertex") == 0){
				counting_params = true;
				numVerticies = atoi(thirdWord.c_str());
			}
			else{
				counting_params = false;
			}
			if(strcmp(secondWord.c_str(), "face") == 0){
				numFaces = atoi(thirdWord.c_str());
			}
		}
		else if(counting_params && strcmp(currentWord.c_str(), "property") == 0){
			param_count++;
		}
	}

	vector<Point3> verticies(numVerticies);
	vector<vector<Point3> > triangles(numFaces);

	//Read in the verticies
	Point3 tempPoint;
	for(int i = 0; i < numVerticies; i++){
		plyFile >> currentWord;
		tempPoint.x = atof(currentWord.c_str());

		plyFile >> currentWord;
		tempPoint.y = atof(currentWord.c_str());

		plyFile >> currentWord;
		tempPoint.z = atof(currentWord.c_str());

		verticies.at(i) = tempPoint;

		//Read in any unused data and ignore it
		for(int j = 0; j < param_count - 3; j++){
			plyFile >> currentWord;
		}
	}

	//Create each triangle as described by the face entries in the file
	vector<Point3> curTriangle(4);
	Vector3 curNormal;
	Point3 normalAsPoint;
	Point3 curPointA;
	Point3 curPointB;
	Point3 curPointC;
	for(int i = 0; i < numFaces; i++){
		//Read in number of verticies (ignore as it is assumed to be 3)
		plyFile >> currentWord;

		plyFile >> currentWord;
		curPointA = verticies.at(atoi(currentWord.c_str()));

		plyFile >> currentWord;
		curPointB = verticies.at(atoi(currentWord.c_str()));

		plyFile >> currentWord;
		curPointC = verticies.at(atoi(currentWord.c_str()));

		//Calculate the normal of the given triangle
		curNormal = (curPointB - curPointA) ^ (curPointC - curPointA);
		normalAsPoint = Point3(curNormal.x,curNormal.y,curNormal.z);

		curTriangle[0] = curPointA;
		curTriangle[1] = curPointB;
		curTriangle[2] = curPointC;
		curTriangle[3] = normalAsPoint;

		triangles.at(i) = curTriangle;
	}

	plyFile.close();

	return triangles;
}